#!/usr/bin/env python
# -------
# Imports:
# -------
import os, pickle, logging
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import users
from settings import *
from core.models import *
from datetime import datetime

# ----------------------------------------------
class GenerateCellComplex(webapp.RequestHandler):
# ----------------------------------------------
    # ------------
    def post(self):
    # ------------
		# Paramaters
        tImgId = int(self.request.get('thresholdedImgId'))

        # Query for the thresholded (binary) image
        tImg = ThresholdedImage.get_by_id(tImgId)
       
        # Make sure the thresholded image exists
        if tImg is not None:
            # Query for the corresponding cell complex 
            cellComplexQuery = CellComplex.all()
            cellComplexQuery.filter('thresholdedImage =', tImg)
            cellComplexes = cellComplexQuery.fetch(1)

            # If we haven't built this cell complex before, build it now
            if len(cellComplexes) == 0:
                # Constant offsets
                vertOffset = [(-1, -1), (-1, 1), (1, -1), (1, 1)]
                edgeOffset = [(-1, 0), (1, 0), (0, -1), (0, 1)]

                # Cell complex representation
                zero = []
                one = []
                two = []

                # Load the image
                (width, height, pixels, metadata) = tImg.simplify()

                # Data structure to lookup indices 
                xRange = range(width)
                yRange = range(height)
                lookup = {}

                # Loop through the cells of the image
                for y in yRange:
                    for x in xRange:
                        # Only consider "on" pixels
                        if pixels[y][x]:

                            # Add all the vertices
                            for vO in vertOffset:
                                j = (2*y) + vO[0]
                                i = (2*x) + vO[1]
                                
                                # See if the pixel is already in the lookup table
                                if (i,j) not in lookup:
                                    # Add the pixel to the cell complex
                                    zero.append((i,j))

                                    # Add the vertex to the lookup table
                                    lookup[i,j] = len(zero) - 1

                            # Add the edges
                            edgeList = []
                            for vE in edgeOffset:
                                j = (2*y) + vE[0]
                                i = (2*x) + vE[1]
                                
                                # See if the edge is already in the lookup table
                                if (i, j) not in lookup:
                                    # Vertical edge
                                    if vE[0] == 0:
                                        one.append((lookup[i, j - 1], lookup[i, j + 1]))

                                    # Horizontal edge
                                    else:
                                        one.append((lookup[i - 1, j], lookup[i + 1, j]))

                                    # Add the edge to the lookup table & the edge list
                                    lookup[i,j] = len(one) - 1
                                edgeList.append(lookup[i,j])

                            # Add the face
                            two.append((edgeList))

                # Put together the cell complex
                cellComplex = (zero, one, two)

                # Perform exhaustive thinning to compute R, I
                cc = CellComplex()
                R, I = cc.thin(cellComplex)

                # Store the cell complex in the datastore
                cc.originalImage = tImg.source_image
                cc.thresholdedImage = tImg
                cc.cellComplex = db.Blob(pickle.dumps(cellComplex))
                cc.R = db.Blob(pickle.dumps(R))
                cc.I = db.Blob(pickle.dumps(I))
                cc.put()
                
                # How many iterations?
                maxIt = max([max(r) for r in R])


            else:
                cc = cellComplexes[0]
                R = pickle.loads(cc.R)
                maxIt = max([max(r) for r in R])
            
            # Write out the cell complex
            out = simplejson.dumps((cc.key().id(), maxIt))
            self.response.out.write(out)

        else:
            self.error(404)
